#include "ps_support.h"

void ps_strcpy(str dest, str src){
	while(*src){
		*dest++ = *src++;
	}
	*dest = '\0';
}

void ps_strncpy(str dest, str src, strsize count){
	while(*src && count--){ //*src != '\0' and count != 0
		*dest++ = *src++;
	}
	*dest = '\0';
}

void ps_strcpysub(str dest, str src, strsize start, strsize end){
	src += start;
	ps_strncpy(dest, src, end-start);
}

strsize ps_strlen(str s){
	strsize count = 0;
	while (s[count])
		count++;
	return count;
}

str ps_strchr(str s, char c){ 
	while(*s){
		if(*s == c) return s;
		s++;
	}
	return null;
}

//searches a string from the end to the beginning and returns a pointer to the character if found
str ps_strrchr(str s, char c){ 
    strsize len = ps_strlen(s);
    s += len;
    while(len--)
        if(*--s == c) return s;
    return null;
}

void ps_strcat(str dest, str src){
	dest += ps_strlen(dest);
	ps_strcpy (dest, src);
}

void ps_strncat(str dest, str src, strsize count){
	strsize len = ps_strlen(dest);
	dest += len;
	ps_strncpy(dest, src, count-len);
}

bool ps_strequal (str s1, str s2){
	while(*s1 || *s2){
		if(*s1++ != *s2++)
			return false;		// strings not equal	
	}
	return true;
}

bool ps_strnequal (str s1, str s2, strsize count){
	while(count-- && (*s1 || *s2)){
		if(*s1++ != *s2++)
			return false;		// strings not equal	
	}
	return true;
}

char ps_charucase(char c){
	if(c >= 'a' && c <= 'z')
		return (c - ('a' - 'A'));
	return c;

}

char ps_charlcase(char c){
	if(c >= 'A' && c <= 'Z')
		return (c + ('a' - 'A'));
	return c;
}

void ps_strucase(str s){
	while(*s){
		*s = ps_charucase(*s);
		s++;
	}
}

void ps_strlcase(str s){
	while(*s){
		*s = ps_charlcase(*s);
		s++;
	}
}

bool ps_strcasecmp (str s1, str s2){
	char c1, c2;
	while(*s1 || *s2){
		c1 = *s1++;
		c2 = *s2++;
		if(ps_charlcase(c1) != ps_charlcase(c2))
			return false;
	}
	return true;
}

bool ps_strncasecmp (str s1, str s2, strsize count){
	char c1, c2;
	while(count-- && (*s1 || *s2)){
		c1 = *s1++;
		c2 = *s2++;
		if(ps_charlcase(c1) != ps_charlcase(c2))
			return false;
	}
	return true;
}

u16 ps_charinstr (str s1, char c){
	u16 count = 0;
	while(*s1){
		if(*s1 == c){
			s1++;
			count++;
		}
	}
	return count;
}

/* commented version
str ps_strstr(str s, str toFind){
	str p = toFind;
	str start = null;
	while(*s){
		if(*s == *p){
			//found first equal pair of characters
			start = s;
			while(true){
				s++; p++; //increase position in s and toFind
				if(*p == '\0'){	return start; }//matched the complete toFind string
				if(*s == '\0'){	return null; }//reached end of s before comparing all characters from toFind
				if(*s == *p){
					//good, go on checking
				}
				else{
					//bad, strings are inequal
					p = toFind; //reset p to the beginning of the toFind string so we can begin from the beginning
					break; //s is at the inequal position...
				}
			}
		}
		else{ //...so we don't want to go to the next position if we return from the second while(true) loop
			s++;
		}
	}
	return null;
}
*/
str ps_strstr(str s, str toFind){ //its freaking pointer magic ;D
	str p = toFind;
	str start = null;
	while(*s){
		if(*s == *p){
			start = s;
			do{
				if(*++p == '\0'){	return start; }//matched the complete toFind string
				if(*++s == '\0'){	return null; }//reached end of s before comparing all characters from toFind
			}while(*s == *p);
			p = toFind;
		}
		else{ //...so we don't want to go to the next position if we return from the second while(true) loop
			s++;
		}
	}
	return null;
}

//if an - symbol is present in the string, it's counted as "not an integer". Is that correct? I vote yes.
bool ps_strisint(str s){
	char c = *s;

	if(c == '\0') return false;
	if(c == '-') *s++;

	while(*s){
		c = *s++;
		if(c < '0' || c > '9')
			return false;
	}
	return true;
}

bool ps_strisfloat(str s){
	char c = *s;
	bool dot = false;

	if(c == '\0') return false;
	if(c == '-') *s++;

	while(*s){
		c = *s++;
		if(c == '.'){
			if(dot){ //second dot
				return false;
			}
			else{
				dot = true;
			}
		}
		else if(c < '0' || c > '9')
			return false;
	}
	return true;
}

//Supports every freakin thing... for integers that is
s32 ps_strtoint(str s){
	s32 value = 0;
	s8 sign = 1;
	char c = *s;

	if(c == '\0') return 0;
	if(c == '-'){
		sign = -1;
		c = *++s;
	}
	else if(c == '+'){//WTF what's this for? xD
		c = *++s;
	}

	while(c >= '0' && c <= '9'){
		value = value*10 + (c - '0');
		c = *++s;
	}

	return sign*value;
}

//GO HERE//Not needed (ps_strtofloat that is)
//float ps_strtofloat(str s){


/*
int ps_atoi (str *str)
{
	int		val;
	int		sign;
	int		c;
	
	if (*str == '-')
	{
		sign = -1;
		str++;
	}
	else
		sign = 1;
		
	val = 0;

//
// check for hex
//
	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
	{
		str += 2;
		while (1)
		{
			c = *str++;
			if (c >= '0' && c <= '9')
				val = (val<<4) + c - '0';
			else if (c >= 'a' && c <= 'f')
				val = (val<<4) + c - 'a' + 10;
			else if (c >= 'A' && c <= 'F')
				val = (val<<4) + c - 'A' + 10;
			else
				return val*sign;
		}
	}
	
//
// check for str acter
//
	if (str[0] == '\'')
	{
		return sign * str[1];
	}
	
//
// assume decimal
//
	while (1)
	{
		c = *str++;
		if (c <'0' || c > '9')
			return val*sign;
		val = val*10 + c - '0';
	}
	
	return 0;
}


float ps_atof (str *str)
{
	double	val;
	int		sign;
	int		c;
	int		decimal, total;
	
	if (*str == '-')
	{
		sign = -1;
		str++;
	}
	else
		sign = 1;
		
	val = 0;

//
// check for hex
//
	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
	{
		str += 2;
		while (1)
		{
			c = *str++;
			if (c >= '0' && c <= '9')
				val = (val*16) + c - '0';
			else if (c >= 'a' && c <= 'f')
				val = (val*16) + c - 'a' + 10;
			else if (c >= 'A' && c <= 'F')
				val = (val*16) + c - 'A' + 10;
			else
				return val*sign;
		}
	}
	
//
// check for str acter
//
	if (str[0] == '\'')
	{
		return sign * str[1];
	}
	
//
// assume decimal
//
	decimal = -1;
	total = 0;
	while (1)
	{
		c = *str++;
		if (c == '.')
		{
			decimal = total;
			continue;
		}
		if (c <'0' || c > '9')
			break;
		val = val*10 + c - '0';
		total++;
	}

	if (decimal == -1)
		return val*sign;
	while (total > decimal)
	{
		val /= 10;
		total--;
	}
	
	return val*sign;
}
*/